import time
import joblib
import warnings
import pandas as pd
from django.shortcuts import render
from sklearn.ensemble import VotingClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import cross_val_score
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import GridSearchCV, StratifiedKFold

warnings.filterwarnings('ignore')

# 启动核心预测程序
def major():
    try:
        test = pd.read_csv('./static/data/datasets/test.csv')
        train = pd.read_csv('./static/data/datasets.csv')
        predictors = train.drop(['stroke', 'id'], axis=1)
        target = train["stroke"]
        x = train
        y = target

        model3 = RandomForestClassifier(n_estimators=10, max_depth=2)

        try:
            model = joblib.load('./static/data/vot.model')
            print("模型加载成功")
        except:
            joblib.dump(model3, './static/data/vot.model')
            model = joblib.load('./static/data/vot.model')
            print("模型创建成功")

        modelgsKNN = VotingClassifier(estimators=[('RF', model)], voting='hard')
        for model, label in zip([model, modelgsKNN], ['RF']):
            scores = cross_val_score(model, x, y, cv=5, scoring='accuracy')  # 交叉验证
            acc = scores.mean()
            print('{}准确率平均数:{}'.format(label, acc))

        modelgsKNN.fit(predictors, target)

        # 分类结果
        ids = test['id']
        predictions = modelgsKNN.predict(test.drop(['stroke', 'id', 'predict'], axis=1))

        # 将输出转换为dataframe并保存到submission.csv文件中
        output = pd.DataFrame({'id': ids, 'predict': predictions})
        output.to_csv('./static/data/submission_RF.csv', index=False)

        # 将得到的预测结果写进text.csv里
        data = pd.read_csv(r'./static/data/datasets/test.csv')
        data1 = pd.read_csv(r'./static/data/submission_RF.csv')
        data['predict'] = data1['predict']
        data.to_csv(r'./static/data/datasets/test.csv', index=False, sep=',')
    except Exception as e:
        print(e)
    return acc


# 启动单条数据预测
def testone(gender, age, hypertension, heart_disease, ever_married, work_type, Residence_type, avg_glucose_level, bmi,
            smoking_status):
    test = pd.DataFrame({
        'id': [0],
        'gender': [gender],
        'age': [age],
        'hypertension': [hypertension],
        'heart_disease': [heart_disease],
        'ever_married': [ever_married],
        'work_type': [work_type],
        'Residence_type': [Residence_type],
        'avg_glucose_level': [avg_glucose_level],
        'bmi': [bmi],
        'smoking_status': [smoking_status],
        'stroke': [0],
        'predict': [0]
    })
    pd.set_option('display.max_columns', None)
    pd.set_option('display.max_rows', None)
    print(test)
    warnings.filterwarnings('ignore')
    train = pd.read_csv('./static/data/datasets/train.csv')
    predictors = train.drop(['stroke', 'id'], axis=1)
    target = train["stroke"]

    kfold = StratifiedKFold(n_splits=10)

    # KNN性能测试
    knn_param_grid = {'n_neighbors': [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21]}
    modelgsKNN = GridSearchCV(estimator=KNeighborsClassifier(), param_grid=knn_param_grid, cv=kfold,
                              scoring="accuracy",
                              n_jobs=-1, verbose=1)
    modelgsKNN.fit(predictors, target)

    # 分类结果
    predictions = modelgsKNN.predict(test.drop(['stroke', 'id', 'predict'], axis=1))[0]
    if predictions == 0:
        predictions = '诊断为未患中风'
    elif predictions == 1:
        predictions = '诊断为中风'
    print("检测结果:", predictions)
    genders = {'1': "男", '0': "女"}
    hypertensions = {'1': "有高血压", '0': "无高血压"}
    heart_diseases = {'1': '有心脏病', '0': '无心脏病'}
    ever_marrieds = {'1': '已婚', '0': '未婚'}
    works = {'0': '私人企业', '1': '政府工作', '2': '自由职业者', '3': '从未工作', '4': '儿童'}
    Residences = {'0': '农村', '1': '城市'}
    smoke = {'0': '从不吸烟', '1': '不知道', '2': '以前吸烟', '3': '吸烟'}
    info = '性别:' + genders[str(gender)] + '\t' + '/年龄:' + age + '\t' + '/' + hypertensions[hypertension] + '\t' + '/' + \
           heart_diseases[
               heart_disease] + '\t' + '/' + ever_marrieds[
               ever_married] + '\t' + '/工作:' + works[
               work_type] + '\t' + '/住宅类型:' + Residences[
               Residence_type] + '\t' + '/平均血糖水平值:' + avg_glucose_level + '\t' + '/BMI值:' + bmi + '\t' + '/' + smoke[
               smoking_status]
    return info, predictions


def index(request):
    info = '开始预测中风数据'
    if request.method == "POST":
        try:
            test_file = request.FILES.get('test')
            df = pd.read_csv(test_file)
            df.to_csv('./static/data/datasets/test.csv', encoding='utf_8_sig', index=False)
            print("需预测的数据文件上传成功！")
            print("程序启动...")
            s1 = time.time()
            acc = round(major(), 3)
            s2 = time.time()
            a = 1
            note = '所用时间: ' + str(round(s2 - s1, 2)) + 's 点我返回'
        except Exception as e:
            info = '数据上传失败，请重新尝试！'
            print("程序出错:", e)
    return render(request, "index.html", locals())


def test_one(request):
    try:
        if request.method == "POST":
            gender = request.POST['gender']
            age = request.POST['age']
            hypertension = request.POST['hypertension']
            heart_disease = request.POST['heart_disease']
            ever_married = request.POST['ever_married']
            work_type = request.POST['work_type']
            Residence_type = request.POST['Residence_type']
            avg_glucose_level = request.POST['avg_glucose_level']
            bmi = request.POST['bmi']
            smoking_status = request.POST['smoking_status']
            start = time.time()
            info, predictions = testone(gender, age, hypertension, heart_disease, ever_married, work_type, Residence_type,
                                        avg_glucose_level, bmi, smoking_status)
            print(predictions)
            end = time.time()
            times = round(end - start, 3)
            a = 1
    except Exception as e:
        info = '数据上传失败，请重新尝试！'
        print("程序出错:", e)
    return render(request, "test_one.html", locals())


# 可视化页面
def visual(request):
    pass
    return render(request, "visual.html", locals())
